
/////////////////
// The program //
/////////////////
#include "./utils.glsl"

#define _Loop_in_inStone(i, j) if(i<LV){ \
            if (intersected(V[i],V[j],p,vec2(10000,10000))){ \
                crossCount ++; \
            } \
        }

bool _inStone(vec2 p, vec2 V[10], int LV){
	int crossCount = 0;
    _Loop_in_inStone(0, 9)
    _Loop_in_inStone(1, 0)
    _Loop_in_inStone(2, 1)
    _Loop_in_inStone(3, 2)
    _Loop_in_inStone(4, 3)
    _Loop_in_inStone(5, 4)
    _Loop_in_inStone(6, 5)
    _Loop_in_inStone(7, 6)
    _Loop_in_inStone(8, 7)
    _Loop_in_inStone(9, 8)
	if (int(mod(float(crossCount),2.0))==1){
		return true;
	}
}

#define _Loop_in_crossStone(i, j) if(i>=LV){return false;}\
            if (intersected(V[i], V[j], a, b)){ \
                return true; \
            } \


bool _crossStone(vec2 a, vec2 b, vec2 V[10], int LV){
	_Loop_in_crossStone(0, 9)
	_Loop_in_crossStone(1, 0)
	_Loop_in_crossStone(2, 1)
	_Loop_in_crossStone(3, 2)
	_Loop_in_crossStone(4, 3)
	_Loop_in_crossStone(5, 4)
	_Loop_in_crossStone(6, 5)
	_Loop_in_crossStone(7, 6)
	_Loop_in_crossStone(8, 7)
	_Loop_in_crossStone(9, 8)
	return false;
}

#define IN_STONE(VV, LV) { \
		if (_inStone(p, VV, LV)){ \
			return true; \
		} \
	} 

#define CROSS_STONE(VV, LV)	{ \
		if (_crossStone(a, b, VV, LV)){ \
			return true; \
		} \
	}

//预设几个形状作为遮挡物
vec2 V1[10];

vec2 V2[10];

vec2 V3[10];

vec2 V4[10];

vec2 V5[10];

bool inStone(vec2 p){
	vec2 VV[10];
	IN_STONE(V1,5)
	IN_STONE(V2,3)
	IN_STONE(V3,5)
	IN_STONE(V4,3)
	IN_STONE(V5,5)
	return false;
}

void initStone(){
	V1[0]=	vec2(131, 176);
	V1[1]=	vec2(216, 141);
	V1[2]=	vec2(290, 174);
	V1[3]=	vec2(290, 279);
	V1[4]=	vec2(154, 279);
	V1[9]=	vec2(154, 279);

	V2[0]=	vec2(503, 220);
	V2[1]=	vec2(569, 289);
	V2[2]=	vec2(462, 379);
	V2[9]=	vec2(462, 379);

	V3[0]=	vec2(194, 579);
	V3[1]=	vec2(264, 642);
	V3[2]=	vec2(236, 757);
	V3[3]=	vec2(90, 802);
	V3[4]=	vec2(91, 679);
	V3[9]=	vec2(91, 679);

	V4[0]=	vec2(556, 591);
	V4[1]=	vec2(612, 745);
	V4[2]=	vec2(486, 885);
	V4[9]=	vec2(486, 885);

	V5[0]=	vec2(299, 846);
	V5[1]=	vec2(344, 919);
	V5[2]=	vec2(400, 853);
	V5[3]=	vec2(442, 998);
	V5[4]=	vec2(216, 969);
	V5[9]=	vec2(216, 969);
}

bool crossStone(vec2 a, vec2 b){
	CROSS_STONE(V1,5)
	CROSS_STONE(V2,3)
	CROSS_STONE(V3,5)
	CROSS_STONE(V4,3)
	CROSS_STONE(V5,5)
	return false;
}

vec4 drawStone(vec2 p){
	if (inStone(p)){
		return vec4(0.0);
	}
	return vec4(1.0);
}

//计算平行光源
vec2 otherLight(vec2 p, vec2 pos, float r){
	vec2 pos1 = p-pos;
	mat2 rout = mat2(0,1,-1,0);
	pos1 = pos1*rout;
	pos1 = pos1*(r/length(pos1));
	pos1 = pos1 + pos;
	return pos1;
}

//计算阴影
float shadow(vec2 p, vec2 pos, float radius) {
	if (crossStone(p,pos)) {
		return 0.0;
	}else{
		return 1.0;
	}
}

//p 目标点
//pos 灯光位置
//color 灯光颜色
//range 光源照亮半径
//radius 光源灯半径
vec4 drawLight(vec2 p, vec2 pos, vec4 color, float range, float radius) {
	// 点到灯的距离
	float ld = length(p - pos);
	
	// 超过灯照半径，则不计算
	if (ld > range) return vec4(0.0);
	if (ld < radius) return vec4(1.0);

	float shad = 1.0;
	float fall = 1.0;

	//越远的光越淡
	fall = (range - ld)/range;
	//fall *= fall;
	
	//计算阴影
	shad = shadow(p, pos, radius);
	bool moreLight = true;
	const int n = 6;	//灯的数量

    if (moreLight){
        if (shad==1.0){
            float s1 = shadow(p, otherLight(p, pos, float(-n)/1.5), radius);
            float s2 = shadow(p, otherLight(p, pos, float(n)/1.5), radius);
            if (s1==1.0 && s2==1.0){
                moreLight =  false;
            }else{
                moreLight = true;
                shad+=s1;
                shad+=s2;
            }
        }else{
            float s1 = shadow(p, otherLight(p, pos, float(-n)/1.5), radius);
            float s2 = shadow(p, otherLight(p, pos, float(n)/1.5), radius);
            if (s1==0.0 && s2==0.0){
                moreLight =  false;
            }else{
                moreLight = true;
                shad+=s1;
                shad+=s2;
            }
        }
    }
	if (moreLight) {
		float count = 1.0;
		for (int r=-n+1; r<0; r+=1){
			shad += shadow(p, otherLight(p, pos, float(r)/1.5), radius);
			count+=1.0;
		}
		for (int r=1; r<=n-1; r+=1){
			shad += shadow(p, otherLight(p, pos, float(r)/1.5), radius);
			count+=1.0;
		}
		shad = shad/count*1.0;
	}


	color.a = color.a*shad*fall;
	return color;

	
	//fall=1.0;

	//画出光源的光斑
	//float source = fillMask(circleDist(p - pos, radius));
	//source = 0.0;
	//return (shad * fall + source) * color;
}

/*
着色器输入
uniform vec3      iResolution;           // viewport resolution (in pixels)
uniform float     iTime;                 // shader playback time (in seconds)
uniform float     iTimeDelta;            // render time (in seconds)
uniform int       iFrame;                // shader playback frame
uniform float     iChannelTime[4];       // channel playback time (in seconds)
uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4      iMouse;                // mouse pixel coords. xy: current (if MLB down), zw: click
uniform sampler2D iChannel0;             // input channel. XX = 2D/Cube
uniform sampler2D iChannel1;             // input channel. XX = 2D/Cube
uniform sampler2D iChannel2;             // input channel. XX = 2D/Cube
uniform sampler2D iChannel3;             // input channel. XX = 2D/Cube
uniform vec4      iDate;                 // (year, month, day, time in seconds)
uniform float     iSampleRate;           // sound sample rate (i.e., 44100)

fragColor => gl_FragColor
fragCoord: 坐标位置(x,y)
*/
void main()
{
	initStone();
    //转换一下坐标系，左上角是原点
    vec2 c = iResolution.xy / 2.0;	//画布中点
	vec2 mouseP = vec2(iMouse.x+0.0, iResolution.y-iMouse.y+0.0);	//目标点
	vec2 p = vec2(gl_FragCoord.x+0.0, iResolution.y-gl_FragCoord.y+0.0);	//目标点
	
	// 背景(高级灰，中间亮，四周暗淡)
	vec4 col = vec4(0.5, 0.5, 0.5, 1.0) * (1.0 - length(c - p)/max(iResolution.x,iResolution.y));

	// 画格子
	col *= clamp(min(mod(p.x, 10.0), mod(p.y, 10.0)), 0.9, 1.0);

	vec2 light1Pos = mouseP.xy;
	vec4 light1Col = vec4(0.9, 0.7, 0.9, 0.60);

	col *= drawStone(p);

	vec4 lCol = drawLight(p, light1Pos, light1Col, 550.0, 6.0);

	col.r += lCol.r*lCol.a;
	col.g += lCol.g*lCol.a;
	col.b += lCol.b*lCol.a;

	gl_FragColor = clamp(col, 0.0, 1.0);
}
